#pragma once
#ifndef __FILE_SERIALIZE_H__
#define __FILE_SERIALIZE_H__

#include <vector>
#include <string>
#include "irrlicht.h"
#include "Core/Commons.h"
#include "Common/FileSerialize.h"
#include "IO/FileSystem/BinaryFile.h"
#include "IReadFile.h"
#include "IWriteFile.h"

// NOT full Implemented, read 80%, write 50%, spiderman only need to read config.
// can't stand for the CBinaryFile to create file serialize class
class FileSerialize {
public:
	//FileSerialize(const char* filename, bool isRead = true);

	// file is must be opened and valid
	FileSerialize(irr::io::IReadFile* file);
	FileSerialize(irr::io::IWriteFile* file);

	void CloseFile() {
		if( m_isRead ) {
			SAFE_DROP(m_reader);
		}
		else {
			SAFE_DROP(m_writer);
		}	
	}

	~FileSerialize() {
		CloseFile();
		SAFE_DEL_ARRAY(m_buffer);
	}

	// return the Serialized bytes

	// base type and string type
	template<typename T>
	irr::s32 Serialize(T &value) {
		if(m_isRead) {
			return m_reader->read(&value, sizeof(value));
		}
		else {
			return m_writer->write(&value, sizeof(value));
		}
	}
	
	irr::s32 Serialize(std::string &value) {
		irr::s32 numOfSerialized = 0;
		irr::s16 length;
		if(m_isRead) {
			numOfSerialized += Serialize(length);
			numOfSerialized += SerializeBuffer(m_buffer, length);
			m_buffer[length] = 0;
			value.assign(m_buffer);
		}
		else {
		}
		
		return numOfSerialized;
	}
	
	/*
	template<typename T>
	irr::s32 Serialize(std::vector<T> &value);
*/
	// TODO: for the buffer
	irr::s32 Serialize(char *value, irr::s32 &numOfValue);
	irr::s32 Serialize(wchar_t *value, irr::s32 &numOfValue);

private:
	void Init();

	// just Serialize Buffer with numOfValue length but don't Serialize the length
	irr::s32 SerializeBuffer(char *value, irr::s32 length);
	bool m_isRead;

	// becasuse irrlicht haven't the both reader and writer class.
	irr::io::IReadFile* m_reader;
	irr::io::IWriteFile* m_writer;
	char* m_buffer;
	irr::s32 m_bufferLength;
};


/*
template<typename T>
irr::s32 FileSerialize::Serialize(std::vector<T> &value) {
	irr::s32 numOfSerialized = 0;
	if(m_isRead) {
		value.clear();
		irr::s16 length;
		T temp;
		
		numOfSerialized += m_reader->read(&length, sizeof(length));
		
		for( irr::s32 i = 0; i < length; ++i) {
			numOfSerialized += m_reader->read(&temp, sizeof(temp));
			value.push_back(temp);
		}
		return numOfSerialized;
	}
	else {
		return 0;
	}
}

*/

class Serializable {
public:
	virtual irr::s32 Serialize(FileSerialize& file) = 0;
};


#endif